<template>
  <div ref="webgl"></div>
</template>

<script>
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { EffectComposer } from "three/examples/jsm/postprocessing/EffectComposer";
import { OutlinePass } from "three/examples/jsm/postprocessing/OutlinePass";
import { RenderPass } from "three/examples/jsm/postprocessing/RenderPass";

export default {
  data() {
    return {
      scene: {},
      mesh: {},
    };
  },
  mounted() {
    this.initThree();
  },
  methods: {
    initThree() {
      this.scene = new THREE.Scene();
      this.camera = new THREE.PerspectiveCamera(
        30,
        window.innerWidth / window.innerHeight,
        1,
        4000
      );
      this.camera.position.set(200, 200, 200);
      this.camera.lookAt(0, 0, 0);

      this.initBox(0);


      this.renderer = new THREE.WebGLRenderer({
        antialias: true,
      });
      this.renderer.setPixelRatio(window.devicePixelRatio);
      this.renderer.setClearColor(0x444444);
      this.renderer.setSize(window.innerWidth, window.innerHeight);
      this.$refs.webgl.appendChild(this.renderer.domElement);

      this.initControl();
      this.initLight();
      this.composer();
      this.animate();
      this.mouseClick();
    },

    mouseClick() {
      window.onresize = () => {
        this.renderer.setSize(window.innerWidth, window.innerHeight);
        this.camera.aspect = window.innerWidth/window.innerHeight;
        this.camera.updateProjectionMatrix();
      };
      document.addEventListener("click", (event) => {
        // .offsetY、.offsetX以canvas画布左上角为坐标原点,单位px
        const px = event.offsetX;
        const py = event.offsetY;
        //屏幕坐标px、py转WebGL标准设备坐标x、y
        //width、height表示canvas画布宽高度
        const x = (px / window.innerWidth) * 2 - 1;
        const y = -(py / window.innerHeight) * 2 + 1;

        //创建一个射线投射器`Raycaster`
        const raycaster = new THREE.Raycaster();
        console.log(raycaster);
        const mouse = new THREE.Vector2();
        mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
        mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
        //.setFromCamera()计算射线投射器`Raycaster`的射线属性.ray
        // 形象点说就是在点击位置创建一条射线，射线穿过的模型代表选中
        raycaster.setFromCamera(mouse, this.camera);

        //.intersectObjects([mesh1, mesh2, mesh3])对参数中的网格模型对象进行射线交叉计算
        // 未选中对象返回空数组[],选中一个对象，数组1个元素，选中两个对象，数组两个元素

        const intersects = raycaster.intersectObjects(this.scene.children);
        console.log("射线器返回的对象", intersects);
        // intersects.length大于0说明，说明选中了模型
        if (intersects.length > 0) {
          // 选中模型的第一个模型，设置为红色
          intersects[0].object.material.color.set(0xff0000);
          //   const clickedModel = intersects[0].object;
          //   // 获取点击模型的世界坐标位置
          //   const modelPosition = clickedModel.getWorldPosition(
          //     new THREE.Vector3()
          //   );
          //   // 更新摄像机位置和目标点
          //   this.camera.position.copy(modelPosition);
          //   this.camera.position.z += 3; // 适当拉开一定距离，可根据需求调整
          //   this.camera.lookAt(modelPosition);
        }
      });
    },
    // 后处理
    composer() {
      //创建后处理对象
      this.composer = new EffectComposer(this.renderer);
      let renderPass = new RenderPass(this.scene, this.camera);
      this.composer.addPass(renderPass);
      let v2 = new THREE.Vector2(window.innerWidth, window.innerHeight);
      let outlinePass = new OutlinePass(v2, this.scene, this.camera);
      outlinePass.selectedObjects = [this.mesh];
      outlinePass.visibleEdgeColor.set(0xff44cc);
      outlinePass.edgeThickness = 4.0;
      outlinePass.edgeStrength = 10;
      outlinePass.pulsePeriod = 2;
      this.composer.addPass(outlinePass);
    },
    //创建灯光
    initLight() {
      let directionalLight = new THREE.DirectionalLight();
      directionalLight.position.set(200, 150, 100);
      let ambient = new THREE.AmbientLight();
      this.scene.add(ambient);
      this.scene.add(directionalLight);
    },
    //控制器
    initControl() {
      this.orbitControls = new OrbitControls(
        this.camera,
        this.renderer.domElement
      );
    },
    //创建盒子
    initBox(index) {
      let material = new THREE.MeshLambertMaterial({
        color: 0xfff4c4,
        transparent: true,
        opacity: 0.8,
      });
      let geometry = new THREE.BoxGeometry(20, 20, 20);
      this.mesh = new THREE.Mesh(geometry, material);
      this.mesh.position.set(30 * index, 20 * index, 25 * index);

      let AxesHelper = new THREE.AxesHelper(100);
      this.scene.add(AxesHelper);
      this.scene.add(this.mesh);
    },
    animate() {
      this.renderer.render(this.scene, this.camera);

      this.composer.render();

      requestAnimationFrame(this.animate);
    },
  },
};
</script>

<style lang="scss" scoped></style>
